package com.axones.planningpoker.dao;

import java.util.ArrayList;
import java.util.Iterator;

import com.axones.planningpoker.bean.ProjectUser;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;

public class ProjectUserDAO {
	private static final String KIND_NAME = "ProjectUser";

	/**
	 * @param projectUser
	 */
	public void add(ProjectUser projectUser) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		datastore.put(convert(projectUser));
	}

	/**
	 * @param projectUser
	 */
	public void delete(ProjectUser projectUser) {
		Entity pu = find(projectUser.getUserId(), projectUser.getProjectId());

		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		datastore.delete(pu.getKey());
	}

	/**
	 * @param id
	 */
	public void deleteByProject(Long id) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Query q = new Query(KIND_NAME);
		q.addFilter("projectId", Query.FilterOperator.EQUAL, id);

		PreparedQuery pq = datastore.prepare(q);

		for (Entity pu : pq.asIterable()) {
			datastore.delete(pu.getKey());
		}
	}

	/**
	 * @param project
	 * @return
	 */
	public String update(ProjectUser projectUser) {
		Entity pu = find(projectUser.getUserId(), projectUser.getProjectId());

		if (pu == null) {
			return "not.found";
		}

		update(projectUser, pu);

		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		datastore.put(pu);

		return "ok";
	}

	/**
	 * @param projectId
	 * @return
	 */
	public ArrayList<ProjectUser> getByUser(long userId) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Query q = new Query(KIND_NAME);
		q.addFilter("userId", Query.FilterOperator.EQUAL, userId);

		PreparedQuery pq = datastore.prepare(q);

		ArrayList<ProjectUser> projectUsers = new ArrayList<ProjectUser>();

		for (Entity pu : pq.asIterable()) {
			projectUsers.add(convert(pu));
		}

		return projectUsers;
	}

	/**
	 * @param projectId
	 * @return
	 */
	public ArrayList<ProjectUser> getByProject(long projectId) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Query q = new Query(KIND_NAME);
		q.addFilter("projectId", Query.FilterOperator.EQUAL, projectId);

		PreparedQuery pq = datastore.prepare(q);

		ArrayList<ProjectUser> projectUsers = new ArrayList<ProjectUser>();

		for (Entity pu : pq.asIterable()) {
			projectUsers.add(convert(pu));
		}

		return projectUsers;
	}

	/**
	 * @param userId
	 * @param projectId
	 * @return
	 */
	private Entity find(long userId, long projectId) {
		DatastoreService datastore = DatastoreServiceFactory
				.getDatastoreService();

		Query q = new Query(KIND_NAME);
		q.addFilter("userId", Query.FilterOperator.EQUAL, userId);
		q.addFilter("projectId", Query.FilterOperator.EQUAL, projectId);

		PreparedQuery pq = datastore.prepare(q);

		Iterable<Entity> results = pq.asIterable();
		Iterator<Entity> it = results.iterator();
		
		if (!it.hasNext()) {
			return null;
		}

		Entity pu = it.next();

		if (it.hasNext()) {
			return null;
		}

		return pu;
	}

	/**
	 * @param i
	 * @return
	 */
	private ProjectUser convert(Entity i) {
		ProjectUser projectUser = new ProjectUser();

		projectUser.setProfile((String) i.getProperty("profile"));
		projectUser.setProjectId((Long) i.getProperty("projectId"));
		projectUser.setUserId((Long) i.getProperty("userId"));

		return projectUser;
	}

	/**
	 * @param projectUser
	 * @return
	 */
	private Entity convert(ProjectUser projectUser) {
		Entity pu = new Entity(KIND_NAME);

		pu.setProperty("profile", projectUser.getProfile());
		pu.setProperty("projectId", projectUser.getProjectId());
		pu.setProperty("userId", projectUser.getUserId());

		return pu;
	}

	/**
	 * @param projectUser
	 * @param pu
	 */
	private void update(ProjectUser projectUser, Entity pu) {
		pu.setProperty("profile", projectUser.getProfile());
	}
}
